package db

import (
	"asuOfficialApi/config"
	"fmt"
	"github.com/gomodule/redigo/redis"
	"github.com/pelletier/go-toml"
	"log"
	"sync"
	"time"
)

var rdsInstance *RedisConn
var rdsOnce sync.Once

var (
	RDS = newCache()
)

type RedisConn struct {
	pool      *redis.Pool
	showDebug bool
}

func (rds *RedisConn) Do(commandName string, args ...interface{}) (reply interface{}, err error) {
	conn := rds.pool.Get()
	defer conn.Close()

	t1 := time.Now().UnixNano()
	reply, err = conn.Do(commandName, args...)
	if err != nil {
		e := conn.Err()
		if e != nil {
			log.Println("redis Do", err, e)
		}
	}
	t2 := time.Now().UnixNano()
	if rds.showDebug {
		fmt.Printf("[redis] [info] [%dus]cmd=%s, err=%s, args=%v, reply=%s\n", (t2-t1)/1000, commandName, err, args, reply)
	}
	return reply, err
}

func (rds *RedisConn) ShowDebug(b bool) {
	rds.showDebug = b
}

func newCache() *RedisConn {
	rdsOnce.Do(func() {
		c := config.Conf.Get("redis").(*toml.Tree)

		host := c.Get("host").(string)
		port := c.Get("port").(int64)
		password := c.Get("password").(string)
		maxIdle := int(c.Get("maxIdle").(int64))
		maxActive := int(c.Get("maxActive").(int64))
		idleTimeout := time.Duration(c.Get("idleTimeout").(int64))
		wait := c.Get("wait").(bool)
		maxConnLifetime := time.Duration(c.Get("maxConnLifetime").(int64))

		pool := redis.Pool{
			Dial: func() (redis.Conn, error) {
				c, err := redis.Dial("tcp", fmt.Sprintf("%s:%d", host, port))
				if err != nil {
					//log.Fatal("redis Dial error ", err)
					panic("redis Dial error " + err.Error())
					return nil, err
				}
				if password != "" {
					if _, err := c.Do("AUTH", password); err != nil {
						c.Close()
						return nil, err
					}
				}
				return c, nil
			},
			TestOnBorrow: func(c redis.Conn, t time.Time) error {
				if time.Since(t) < time.Minute {
					return nil
				}
				_, err := c.Do("PING")
				return err
			},
			MaxIdle:         maxIdle,
			MaxActive:       maxActive,
			IdleTimeout:     idleTimeout,
			Wait:            wait,
			MaxConnLifetime: maxConnLifetime,
		}

		instance := &RedisConn{
			pool: &pool,
		}
		rdsInstance = instance
	})

	return rdsInstance
}
